Помогни ни да направим Uroci.net по - богат! Добави урок

C++ част.7 (Член функции на клас)

C++ » C++
fix3d   трудност:    видян: 43596



Конструктор като оператор конвертор

Съвкупността от едно аргументни конструктори за клас като SmallInt дефинира набор от неявни конвертори, преобразуващи не-SmallInt типове в обекти от тип SmallInt. Стандартните конвертори, ако са необходими, се прилагат над типовете преди извикването на конструктора.

Конструктор, който получава един аргумент като SmallInt(int), служи като оператор за преобразуване между типа на аргумента и класа. SmallInt(int), например, преобразува цели стойности в обекти на

SmallInt.extern f( SmallInt );
int i; // need to convert i into a SmallInt
f( i ); // SmallInt(int) accmplishes this

При обръщението f( i ), i се преобразува в обект на SmallInt чрез извикване на SmallInt(int). Компилаторът конструира временен обект на SmallInt и го изпраща на f().

{SmallInt temp = SmallInt(i);
f(temp);} // a temporary SmallInt Object is created

Фигурните скоби, употребени в примера, показват продължителността на периода на съществуване на генерирания временен обект на SmallInt.

Ако е необходимо преди извикването на SmallInt(int) се прилага стандартен конвертор. Например,

double d;f( d );

става

{// warning: narrowing conversion
SmallInt temp = SmallInt( (int)d );
f(temp);}

Извикването на оператор конвертор се извършва само ако не са възможни други преобразувания. Ако f() беше презаредима функция, както е в следващия пример, SmallInt(int) нямаше да бъде извикана.

f( SmallInt );
f( double );
int ival;// matches f(double) by standard conversion
f( ival );

Аргументът може да бъде и от друг, дефиниран от потребителя клас. Например,

class Token
{public: // ... public membersprivate:
SmallInt tok;// ... rest of Token members};
// create a Smallint object from a Token
SmallInt::SmallInt( Token& t ) { /* ... */ }
extern f( Smallint& );
Token curTok;
main()
{{ // invoke SmallInt( Token& );
f( curTok );}



Оператори конвертори

Операторите за конвертиране, които са специални представители на член функциите на един клас, определят неявното преобразуване на обекти на класа в някакви други типове. SmallInt, например, може да дефинира преобразуване на обект на SmallInt в стойност от тип unsigned int:

SmallInt::Operator unsigned int(){return( (unsigned)value );}
Класът Token, дефиниран по-нататък в текста, може да дефинира много оператори конвертори:

#include "SmallInt.h"
class Token{public:
Token( char *nm, int v1 ): val( v1 ), name( nm ) {}
operator SmallInt() { return val; }
operator char*() { return name; }
operator int() { return val; }// .. rest of public membersprivate:
SmallInt val;
char *name;};

Забележете, че операторите конвертори на Token за SmallInt и int са еднакви. SmallInt::Operator int() е приложен неявно над обекта val на SmallInt в Token::Operator int(). Например,

#include "Token.h"
void f( int i )
{ cout << "nf(int) : " << i;}
Token t1( "integer constant", 127 );
main()
{ Token t2( "friend", 255 );
f( t1 ); // t1.operator int()f( t2 ); // t2.operator int()}

Когато бъде компилирана и изпълнена тази малка програма дава следния резултат:

f(int) : 127f(int) : 255

Един оператор конвертор има следния общ вид:

operator <type> ();

където <type> се замества с определен вграден, произлязъл или класов тип. (Операторите конвертори на масиви или функции не са допустими). Операторите конвертори трябва да бъдат член функции. Те не трябва да определят тип за връщане нито могат да имат списък от аргументи. Всяка от следните декларации, например, е недопустима:

operator int( SmallInt& ); // error:
nonmember class SmallInt{public:int operator int(); // error:
return type operator int( int ); // error:
argument list ...};

Програмистът може явно да извика оператор конвертор като използува една от двете форми на записа за преобразуване. Например,

#include "Token.h"
Token tok( "function", 78 );// function cast notation:
operator SmallInt() SmallInt tokVal = SmallInt( tok );// type cast notation:
operator char*()char *tokString = (char *)tok;

Ако съществува обект на клас, който не е от подходящ тип, и е дефиниран оператор конвертор той ще бъде неявно приложен от компилатора. Например,

#include "Token.h"
extern void f( char *);
Token tok( "enumeration", 8 );
enum { ENUM }; // token constant

main() {
f( tok ); // tok.operator
char*();// explicit functional cast notation
switch ( int(tok) ) // tok.operator int() {case ENUM:{
// tok.operator SmallInt();
SmallInt si = tok;// ...}
}}

Да допуснем, че желаният тип не съответствува точно на никой от операторите конвертори. Ще бъде ли извикан оператор конвертор?

да, ако желаният тип може да бъде получен чрез стандартно преобразуване. Например,

extern void f( double );
Token tok( "constant", 44 );// tok.operator
int() invoked// int ==> double by standard conversionf( tok );

не, ако желаният тип може да бъде получен чрез прилагане на втори оператор конвертор, дефиниран от потребителя върху резултата от първи, дефиниран от потребителя, оператор конвертор. (Ето защо Token дефинира както operator SmallInt() така и operator int()). Например, ако Token не предлага представител на operator int() следното обръщение би било недопустимо:

extern void f(int);
Token tok( "pointer", 37 );// without
Token::Operator int() defined,// this call will generate a compile-time error
f( tok );

Ако Token::Operator int() не е дефиниран, преобразуването на tok към типа int ще изисква извикването на два оператора конвертори, дефинирани от потребителя.

Token::Operator SmallInt();

ще преобразува tok в обект на SmallInt.

SmallInt::Operator int();

ще завърши преобразуването до типа int.

Според правилото, обаче, могат да бъдат прилагани оператори конвертори, дефинирани от потребителя, само от едно ниво. Ако Token::Operator int() не е дефиниран, обръщението f(tok), изискващо аргумент от тип int, предизвиква грешка по време на компилация поради нарушение на типовете.


Страници: «7 8 9 10 11 »

Сподели урока:



Регистрирайте се, за да добавите коментар


Калдейта Ком ЕООД - © 2003-. Всички права запазени.
Препоръчваме: IT Новини